package com.nidu.demo.user.executor.command;

import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.nidu.demo.common.constants.Constants;
import com.nidu.demo.company.ability.CompanyDomainService;
import com.nidu.demo.dept.ability.DepartmentDomainService;
import com.nidu.demo.dept.model.Department;
import com.nidu.demo.post.ability.PositionDomainService;
import com.nidu.demo.post.model.Position;
import com.nidu.demo.user.dto.UserUpdateCmd;
import com.nidu.demo.common.enums.StatusEnum;
import com.nidu.demo.user.ability.UserDomainService;
import com.nidu.demo.user.convertor.UserConvertor;
import com.nidu.demo.user.dto.*;
import com.nidu.demo.user.gateway.UserDepartmentGateway;
import com.nidu.demo.user.gateway.UserGateway;
import com.nidu.demo.user.gateway.UserPositionGateway;
import com.nidu.demo.user.model.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.List;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class UserUpdateCmdExe {
    private final UserConvertor convertor;

    private final UserGateway gateway;

    private final UserDomainService domainService;

    private final CompanyDomainService companyDomainService;

    private final DepartmentDomainService departmentDomainService;

    private final PositionDomainService positionDomainService;

    private final UserGateway userGateway;

    private final UserDepartmentGateway userDeptGateway;

    private final UserPositionGateway userPostGateway;

    public SingleResponse<UserCO> execute(UserUpdateCmd cmd) {
        // 1. 转换为领域对象
        User user = User.update(cmd.getId(), cmd.getUsername(), null, cmd.getNickname(), cmd.getMobile(),
                cmd.getEmail(), cmd.getAvatar(), cmd.getGender(), cmd.getCompanyId(), cmd.getSortOrder());

        // 3. 校验对象
        // 3.1.检查公司是否启用
        companyDomainService.validateCompany(user.getCompanyId());
        // 3.2.检查对象是否存在
        domainService.validateDuplicate(user.getUsername(), user.getMobile(), user.getEmail(), user.getId());
        // 3.3.检查所有部门是否启用
        List<Department> depts = departmentDomainService.validateDepartmentList(cmd.getDeptIds());
        user.setDeptIds(depts.stream().map(Department::getId).collect(Collectors.toSet()));
        // 3.4.检查所有岗位是否启用
        List<Position> posts = this.positionDomainService.validatePositionList(cmd.getPostIds());
        user.setPostIds(posts.stream().map(Position::getId).collect(Collectors.toSet()));

        // 4. 更新用户、部门和职位信息
        User save = this.updateUserInfo(user);

        // 6. 转换为DTO返回
        UserCO userCO = convertor.toClientObject(save);

        return SingleResponse.of(userCO);
    }

    public Response resetPassword(UserResetPasswordCmd cmd) {
        String password = domainService.encodePassword(Constants.DEFAULT_PASSWORD);

        gateway.updatePassword(cmd.getUserId(), password);

        return Response.buildSuccess();
    }

    public Response updatePassword(Long userId, UserUpdatePasswordCmd cmd) {
        domainService.validatePassword(userId, cmd.getOldPassword(), cmd.getNewPassword(), cmd.getConfirmPassword());

        String password = domainService.encodePassword(cmd.getNewPassword());

        gateway.updatePassword(userId, password);

        return Response.buildSuccess();
    }

    public Response updateStatus(Long userId, StatusEnum statusEnum) {
        gateway.updateStatus(userId, statusEnum.getValue());
        return Response.buildSuccess();
    }

    public Response updateProfile(Long userId, UserUpdateProfileCmd cmd) {
        gateway.updateProfile(userId, cmd.getNickname(), cmd.getEmail(), cmd.getGender());
        return Response.buildSuccess();
    }

    public SingleResponse<String> updateAvatar(Long userId, InputStream inputStream) {
        // TODO 文件上传还未实现
        String avatar = null;
        gateway.updateAvatar(userId, avatar);
        return SingleResponse.of(avatar);
    }

    @Transactional
    private User updateUserInfo(User user) {
        User save = userGateway.update(user);
        userDeptGateway.rebindUserDepts(save.getId(), user.getDeptIds());
        userPostGateway.rebindUserPosts(save.getId(), user.getPostIds());
        return save;
    }
}
